/**
 * 
 */
package info.niwota.web.jetty;

/**
 * 
 */

import info.niwota.web.Session;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.mortbay.io.WriterOutputStream;
import org.mortbay.jetty.HttpConnection;
import org.mortbay.jetty.HttpFields;
import org.mortbay.jetty.HttpHeaders;
import org.mortbay.jetty.Response;
import org.mortbay.util.TypeUtil;
import org.mortbay.util.URIUtil;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;

/**
 * @author qiangli
 */
public class BaseHandler {
	protected static HashMap<String, Session> sessions = new HashMap<String, Session>();
	
	protected static final String SESSION_KEY = "session";

	protected static final int BUFSIZE = 1024;

	protected Context ctx;

	public BaseHandler(Context ctx) {
		this.ctx = ctx;
	}

	public boolean handle(String path, HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		return false;
	}

	protected void setContentLength(HttpServletResponse res, long length) {
		if (res instanceof Response) {
			HttpFields fields = ((Response) res).getHttpFields();
			if (length > 0) {
				fields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER, length);
			}

		} else {
			if (length > 0) {
				res.setHeader(HttpHeaders.CONTENT_LENGTH, TypeUtil
						.toString(length));
			}
		}
	}

	protected void sendContent(HttpServletResponse res, String s, String mime)
			throws IOException {
		res.setStatus(HttpServletResponse.SC_OK);
		res.setContentType(mime);
		res.getWriter().println(s);
	}

	protected void sendContent(HttpServletResponse res, InputStream in, String mime)
			throws IOException {
		res.setStatus(HttpServletResponse.SC_OK);
		res.setContentType(mime);
		//
		OutputStream out = null;
		try {
			out = res.getOutputStream();
		} catch (IllegalStateException e) {
			out = new WriterOutputStream(res.getWriter());
		}
		try {
			// See if a short direct method can be used?
			if (out instanceof HttpConnection.Output) {
				// todo file mapped buffers
				((HttpConnection.Output) out).sendContent(in);
			} else {
				// Write content normally
				// resource.writeTo(out, 0, length));
				copy(in, out);
			}
		} finally {
			in.close();
		}
	}

	protected Session getSession(HttpServletRequest req) {
		return (Session) req.getAttribute(SESSION_KEY);
	}

	protected void sendFile(HttpServletRequest req, HttpServletResponse res, File file, String mime)
			throws IOException {
//		long ifModifiedSince = req.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
//		long lastModified = file.lastModified();
//		if (ifModifiedSince > 0 && ifModifiedSince / 1000 > lastModified / 1000) {
//			res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
//			res.setDateHeader(HttpHeaders.LAST_MODIFIED, System
//					.currentTimeMillis());
//			return;
//		}
		//
		long len = file.length();
		setContentLength(res, len);
		InputStream in = new FileInputStream(file);
		sendContent(res, in, mime);
	}

	protected void sendError(String p, HttpServletRequest request, HttpServletResponse response, Exception e)
			throws IOException {
		response.setStatus(HttpServletResponse.SC_OK);
		response.setContentType("text/html");
		PrintWriter w = response.getWriter();
		w.println("Error: " + p + ": <br />");
		e.printStackTrace(w);
	}

	protected void sendAsset(HttpServletRequest req, HttpServletResponse res, String name, String mime)
			throws IOException {
		// AssetFileDescriptor fd = ctx.getAssets().openFd(name);
		// by fd, can't read if content is compressed
		AssetManager am = ctx.getAssets();
		// long len = fd.getLength();
		// setContentLength(res, len);
		// InputStream in = fd.createInputStream();
		InputStream in = am.open(name);
		sendContent(res, in, mime);
	}

	protected void redirectLogin(HttpServletRequest req, HttpServletResponse res) throws IOException {
		res.sendRedirect(res.encodeRedirectURL(URIUtil.addPaths("/login",
				URIUtil.SLASH)));
	}

	protected void redirectHome(HttpServletRequest request, HttpServletResponse response) throws IOException {
		response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths("/home",
				URIUtil.SLASH)));
	}

	protected String nvl(String s) {
		return s == null ? "" : s;
	}

	protected void copy(InputStream is, Appendable out) throws IOException {
		BufferedReader r = new BufferedReader(new InputStreamReader(is),
				BUFSIZE);
		while (true) {
			String l = r.readLine();
			if (l == null) {
				break;
			}
			out.append(l);
			out.append("\r\n");
		}
	}

	protected void copy(InputStream is, OutputStream os) throws IOException {
		byte[] buf = new byte[BUFSIZE];
		while (true) {
			int read = is.read(buf);
			if (read == -1) {
				break;
			}
			if (read > 0) {
				os.write(buf, 0, read);
			}
		}
		os.flush();
	}

	protected String toString(InputStream is) throws IOException {
		StringBuffer sb = new StringBuffer();
		try {
			copy(is, sb);
		} finally {
			is.close();
		}
		return sb.toString();
	}

	protected InputStream format(Context ctx, String name, Object[] data)
			throws Exception {
		InputStream is = null;
		AssetManager am = ctx.getAssets();
		is = am.open(name);
		return is;
	}

	protected String getAsString(Context ctx, String name) throws IOException {
		InputStream is = null;
		try {
			AssetManager am = ctx.getAssets();
			is = am.open(name);
			String template = toString(is);
			return template;
		} finally {
			if (is != null) {
				is.close();
			}
		}
	}

	protected CharSequence findLabel(Context ctx, String pkg)
			throws NameNotFoundException {
		PackageManager pm = ctx.getPackageManager();
		ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
		return ai.loadLabel(pm);
	}
	
	
	protected String filterCookies(String pkg, Cookie[] cookies) {
		if (cookies == null || cookies.length == 0) {
			return null;
		}
		final String pname = pkg + ".";
		final int plen = pname.length();
		StringBuilder sb = new StringBuilder();
		final String sep = ";";
		for (int i = 0; i < cookies.length; i++) {
			String n = cookies[i].getName();
			String v = cookies[i].getValue();
			if (n.startsWith(pname)) {
				sb.append(n.substring(plen)+"="+v+sep);
			}
		}
		return (sb.length() > 0 ? sb.toString() : null);
	}

	protected String scan(Cookie[] cookies, String key) {
		if (cookies == null || cookies.length == 0) {
			return null;
		}
		for (int i = 0; i < cookies.length; i++) {
			if (key.equalsIgnoreCase(cookies[i].getName())) {
				return cookies[i].getValue();
			}
		}
		return null;
	}
}
